package com.espirit.common;

import java.io.CharArrayWriter;
import java.util.Map;

import javax.annotation.Resource;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.views.freemarker.FreemarkerManager;
import org.apache.struts2.views.freemarker.ScopesHashModel;
import org.springframework.mail.MailException;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;

import com.googlecode.cswish.Config;
import com.googlecode.cswish.struts.spring.ObjectFactory;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.util.ValueStack;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateModel;
import freemarker.template.TemplateModelException;

@Service
public class MailService {
	
	private final Log logger = LogFactory.getLog(MailService.class);
    
	@Resource
	private ObjectFactory objectFactory;
	
	@Resource
	private Config config;
	
	@Inject
	protected FreemarkerManager freemarkerManager;
	
	@Resource
    private JavaMailSender javaMailSender;
    
    private String encoding = "UTF-8";

    public boolean send(String title, String templateLocation, String[] toEmails, Map parameters) {
        MimeMessage msg = javaMailSender.createMimeMessage();
        MimeMessageHelper helper = new MimeMessageHelper(msg);
        
        try {
            helper.setFrom(config.getMailFrom());
            helper.setSubject(title);
            helper.setTo(toEmails);
            helper.setText(getMessage(templateLocation, parameters), true);
            javaMailSender.send(msg);
            
        } catch (MessagingException e) {
            if(logger.isWarnEnabled()) {
                logger.warn("Mail context error! the email title is " + title);
            }
            return false;
        } catch (MailException me) {
            if(logger.isWarnEnabled()) {
                logger.warn("Send mail failed: the mail title is " + title, me);
            }
            return false;
        }
        return true;    
    }
    
    
    /**
     * Get email from template 
     * 
     * @return the email context need to send
     */
    private String getMessage(String templateLocation, Map model) {
    	if (freemarkerManager == null) {
			objectFactory.injectInternalBeans(this);
		}
    	try {
			Configuration configuration = freemarkerManager.getConfiguration(ServletActionContext.getServletContext());
			Template template = configuration.getTemplate(templateLocation, encoding);
			TemplateModel templateModel = createModel(model, configuration);
			CharArrayWriter parentCharArrayWriter = new CharArrayWriter();
			template.process(templateModel, parentCharArrayWriter);
			return parentCharArrayWriter.toString();
    	} catch (Exception ex) {
			logger.error("Failed to generate the mail context", ex);
		}
    	return "";
    }

	private TemplateModel createModel(Map model, Configuration configuration) throws TemplateModelException {
        ServletContext servletContext = ServletActionContext.getServletContext();
        HttpServletRequest request = ServletActionContext.getRequest();
        HttpServletResponse response = ServletActionContext.getResponse();
        ActionInvocation invocation = ActionContext.getContext().getActionInvocation();
        ValueStack stack = ServletActionContext.getContext().getValueStack();

        Object action = null;
        if(invocation!= null ) {
        	action = invocation.getAction(); //Added for NullPointException
        }
        ScopesHashModel templateModel = freemarkerManager.buildTemplateModel(stack, action, servletContext,
        		request, response, configuration.getObjectWrapper());
        templateModel.putAll(model);
        return templateModel;
    }
}
